#ifndef _FH_DMA_H_
#define _FH_DMA_H_
#include <linux/types.h>
#include "common.h"

#define FH_CHANNEL_MAX_TRANSFER_SIZE (2048)

struct dw_lli
{
    /* values that are not changed by hardware */
    u32 sar;
    u32 dar;
    u32 llp; /* chain to next lli */
    u32 ctllo;
    /* values that may get written back: */
    u32 ctlhi;
    /* sstat and dstat can snapshot peripheral register state.
     * silicon config may discard either or both...
     */
    u32 sstat;
    u32 dstat;
    u32 reserve;
};


/* transfer use below */
struct dma_transfer
{
    u32 channel_number;
/* user should set the para below */
#define DMA_M2M (0)       /* MEM <=> MEM */
#define DMA_M2P (1)       /* MEM => peripheral A */
#define DMA_P2M (2)       /* MEM <= peripheral A */
#define DMA_P2P (3)       /* peripheral A <=> peripheral B */
    u32 fc_mode;  /* ip->mem. mem->mem. mem->ip */
#define DMA_HW_HANDSHAKING (0)
#define DMA_SW_HANDSHAKING (1)
    u32 src_hs;  /* src */
    /* if use hw handshaking ,you need to set the hw handshaking number, this */
    /* SOC defined */
    u32 src_per;  /* src hw handshake number */
/* u32            irq_mode;//for each transfer,irq maybe not same. */
/* suggest for the default(transfer isr) */
#define DW_DMA_SLAVE_WIDTH_8BIT (0)
#define DW_DMA_SLAVE_WIDTH_16BIT (1)
#define DW_DMA_SLAVE_WIDTH_32BIT (2)
    u32 src_width;
/* the user should reference the hw handshaking watermark.. */
#define DW_DMA_SLAVE_MSIZE_1 (0)
#define DW_DMA_SLAVE_MSIZE_4 (1)
#define DW_DMA_SLAVE_MSIZE_8 (2)
#define DW_DMA_SLAVE_MSIZE_16 (3)
#define DW_DMA_SLAVE_MSIZE_32 (4)
#define DW_DMA_SLAVE_MSIZE_64 (5)
#define DW_DMA_SLAVE_MSIZE_128 (6)
#define DW_DMA_SLAVE_MSIZE_256 (7)
    u32 src_msize;
    u32 src_add;
#define DW_DMA_SLAVE_INC (0)
#define DW_DMA_SLAVE_DEC (1)
#define DW_DMA_SLAVE_FIX (2)
    u32 src_inc_mode;  /* increase mode: increase or not change */
    /* #define DMA_DST_HW_HANDSHAKING    (0) */
    /* #define DMA_DST_SW_HANDSHAKING    (1) */
    u32 dst_hs;  /* src */
    /* if use hw handshaking ,you need to set the hw handshaking number, this */
    /* SOC defined */
    u32 dst_per;  /* dst hw handshake number */
    /* #define    DW_DMA_SLAVE_WIDTH_8BIT     (0) */
    /* #define    DW_DMA_SLAVE_WIDTH_16BIT     (1) */
    /* #define    DW_DMA_SLAVE_WIDTH_32BIT     (2) */
    u32 dst_width;
    /* #define DW_DMA_SLAVE_MSIZE_1         (0) */
    /* #define DW_DMA_SLAVE_MSIZE_4         (1) */
    /* #define DW_DMA_SLAVE_MSIZE_8         (2) */
    /* #define DW_DMA_SLAVE_MSIZE_16         (3) */
    /* #define DW_DMA_SLAVE_MSIZE_32         (4) */
    /* #define DW_DMA_SLAVE_MSIZE_64         (5) */
    /* #define DW_DMA_SLAVE_MSIZE_128         (6) */
    /* #define DW_DMA_SLAVE_MSIZE_256         (7) */
    u32 dst_msize;
    u32 dst_add;
    /* #define DW_DMA_SLAVE_INC        (0) */
    /* #define DW_DMA_SLAVE_DEC        (1) */
    /* #define DW_DMA_SLAVE_FIX        (2) */
    u32 dst_inc_mode;  /* increase mode: increase or not change */
    #define ADDR_RELOAD      (0x55)
    //#define SRC_ADDR_RELOAD      (0)
    u32 src_reload_flag;
    u32 dst_reload_flag;
    /* total sizes, unit: src_width/DW_DMA_SLAVE_WIDTH_8BIT... */
    /* exg: src_width = DW_DMA_SLAVE_WIDTH_32BIT. trans_len = 2...means that: */
    /* the dma will transfer 2*4 bytes.. */
    /* exg: src_width = DW_DMA_SLAVE_WIDTH_8BIT. trans_len = 6...means that: the */
    /* dma will transfer 1*6 bytes.. */
    u32 trans_len;
    u32 priority;
        /* period len.. */
    u32 period_len;
#define AHB_MASTER_1    0
#define AHB_MASTER_2    1
#define AHB_MASTER_3    2
#define AHB_MASTER_4    3
    u32 src_master_sel;
    u32 dst_master_sel;

};

void dma_init(void);
void *get_dma_tx_lli_head(void);
void *get_dma_rx_lli_head(void);
void wait_dma_xfer_done(u32 channel);
void handle_single_transfer(struct dma_transfer *p_transfer,void *p_lli_in);
#endif